/* Copyright (c) 2016 Lucky Byte, Inc.
 */
package com.lucky_byte.pay.p091;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.lucky_byte.pay.jar.JdbcRecord;

/**
 * 多线程网络服务器
 */
public class PooledServer implements Runnable
{
	private static final Logger logger = LogManager.getLogger();

	private JdbcRecord ichnl;
	private JdbcRecord host;
	private ServerSocket server_socket = null;
	private boolean is_stopped = true;
	private ExecutorService thread_pool;

	public PooledServer(JdbcRecord ichnl, JdbcRecord host) {
		this.ichnl = ichnl;
		this.host = host;
		this.thread_pool = Executors.newCachedThreadPool();
	}

	public JdbcRecord getIChnl() {
		return this.ichnl;
	}

	private String getBindAddr(int listen_addr) {
		switch (listen_addr) {
		case 1:
			return "0.0.0.0";
		case 2:
			return "127.0.0.1";
		case 3:
			return host.getString("ipaddr");
		case 4:
			return host.getString("ipaddr_priv");
		default:
			logger.error("监听地址[{}]无效.", listen_addr);
			return "127.0.0.1";
		}
	}

	public void run() {
		try {
			int listen_addr = ichnl.getInteger("listen_addr");
			int listen_port = ichnl.getInteger("listen_port");
			this.server_socket = new ServerSocket(listen_port, 100,
					InetAddress.getByName(getBindAddr(listen_addr)));
			logger.info("启动 POS 009.1 接入服务，模式[{}]，服务端口[{}]，进程[{}]...",
					ichnl.getString("mode_name"), listen_port,
					ManagementFactory.getRuntimeMXBean().getName());
		} catch (IOException e) {
			logger.error("创建监听 Socket 错误[{}].", e.getMessage());
			return;
		}
		this.is_stopped = false;
		while (!this.is_stopped) {
			try {
				Socket accept_socket = this.server_socket.accept();
				accept_socket.setSoTimeout(30 * 1000);
				if (ichnl.getBoolean("disabled")) {
					logger.debug("POS 009.1 接入服务模式[{}]已禁用，拒绝服务.",
							ichnl.getString("mode_name"));
					accept_socket.close();
					continue;
				}
				InetAddress addr = accept_socket.getInetAddress();
				logger.info("接收客户端[{}][{}]的连接，开始处理...",
						addr.getHostAddress(), accept_socket.getPort());
				this.thread_pool.execute(new Worker(accept_socket, ichnl));
			} catch (IOException e) {
				if (this.is_stopped) {
					break;
				}
				logger.error("接收客户端连接错误[{}].", e.getMessage());
			}
		}
		this.thread_pool.shutdown();
		logger.info("POS 009.1 接入服务[{}]模式停止运行.",
				ichnl.getString("mode_name"));
	}

	/**
	 * 停止服务器
	 */
	public synchronized void stop() {
		if (!this.is_stopped) {
			this.is_stopped = true;
			try {
				this.server_socket.close();
			} catch (IOException e) {
				logger.catching(e);
			}
		}
	}

}
